package com.example.usage.aop.log;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * @author jiangzhe
 * @create 2022/4/1 10:39
 */
@Aspect
@Component
@Slf4j
@Order(1)
public class OptLogAspect1 {

    @Pointcut("@annotation(com.example.usage.aop.log.OptLogAnno)")
    public void pointCut(){}

    @Before("pointCut()")
    public void before(){
        log.info("OptLogAspect1 -- before");
    }

    @AfterReturning(pointcut = "pointCut()", returning = "jsonObj")
    public void afterReturning(JoinPoint joinPoint, Object jsonObj){
        handleLog(joinPoint, null, joinPoint);
    }

    @AfterThrowing(value = "pointCut()",throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint,Exception e){
        handleLog(joinPoint, e,null);
    }

    protected void handleLog (final JoinPoint joinPoint,final Exception e,Object jsonResult){
        try{
            OptLogEntity logOperate = new OptLogEntity();
            OptLogAnno controllerLog = getAnnotationLog(joinPoint);
            if(controllerLog == null){
                return ;
            }
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            // 请求的类名
            String className = joinPoint.getTarget().getClass().getName();
            // 请求的方法名
            String methodName = signature.getName();
            // 请求的方法参数值
            String args = Arrays.toString(joinPoint.getArgs());
            log.info("OptLogAspect1 -- afterReturning 类名:{}, 方法名:{}, 参数：{}", className, methodName, args);
            OptLogAnno userAction = method.getAnnotation(OptLogAnno.class);
            if (userAction != null) {
                // 注解上的描述
                logOperate.setOperation(userAction.value());//操作方法
                logOperate.setModule(userAction.optModule());//模块
            }
            //异常处理
            if(e!=null){
                logOperate.setStatus(-1);
                logOperate.setContent(e.getMessage());
            }else{
                logOperate.setStatus(1);
            }
            logOperate.setUserId("userId 实时获取");
            logOperate.setMethod(className + "." + methodName + "()");
            logOperate.setCreatedTime(new Date());
            log.info("add log {} info to db", logOperate);
        }catch(Exception exp){
            log.error("日志异常信息 {}",exp);
        }
    }

    private OptLogAnno getAnnotationLog(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if(method!=null){
            return method.getAnnotation(OptLogAnno.class);
        }
        return null;
    }
}
